package cin.ufpe.assertgroup.model;

import java.util.HashSet;
import java.util.Set;

public class Structure {
	
	private int numberFeatures;
	private int numberTopFeatures;
	private int numberLeafFeatures;
	private int numberOptionalFeatures;
	private int numberConstraints;
	private int dephTree;
	private Set<String> featuresOnConstraints;
	
	//usadas para calcular o numero medio de features filhas (RoV)
	private int numberNodeFeatures;
	private int numberChildrenFeatures;
	
	public Structure(){
		featuresOnConstraints = new HashSet<String>();
	}
	
	/**
	 * 
	 * @return The total number of features that are present in a feature model
	 */
	public int getNumberFeatures() {
		return numberFeatures;
	}
	
	public void incNumberFeatures(){
		numberFeatures++;
	}
	
	/**
	 * 
	 * @return The number of features that are first direct de-scendants of the feature model root
	 */
	public int getNumberTopFeatures() {
		return numberTopFeatures;
	}
	
	public void incNumberTopFeatures(){
		numberTopFeatures++;
	}
	
	/**
	 * 
	 * @return The number of features with no children or further specializations
	 */
	public int getNumberLeafFeatures() {
		return numberLeafFeatures;
	}
	public void incNumberLeafFeatures(){
		numberLeafFeatures++;
	}
	public int getNumberOptionalFeatures() {
		return numberOptionalFeatures;
	}
	public void incNumberOptionalFeatures(){
		numberOptionalFeatures++;
	}
	public int getNumberConstraints() {
		return numberConstraints;
	}
	public void incNumberConstraints(){
		numberConstraints++;
	}
	
	/**
	 * 
	 * @return The length of the longest path from the feature model root to leaf features in the feature model
	 */
	public int getDephTree() {
		return dephTree;
	}
	public void incDephTree(int dephBranch){
		if (dephTree < dephBranch)
			dephTree = dephBranch;
	}
	public void addFeaturesOnConstraints(String nameFeature){
		featuresOnConstraints.add(nameFeature);
	}
	
	/**
	 * The number of distinct cycles that can be found in the feature model.
	 * Since feature mod-els are in the form of trees, no cycles can exist in a feature model;
	 * however, integrity constraints between the available features can cause cycles.
	 * @return number of integrity constraints of a feature model
	 */
	public int getCyclomaticComplexity(){
		return this.getNumberConstraints();
	}
	
	public int getNumberChildrenFeatures() {
		return numberChildrenFeatures;
	}
	
	public void incNumberChildrenFeatures(int numberChildrenFeatures){
		this.numberChildrenFeatures += numberChildrenFeatures;
	}
	
	public int getNumberNodeFeatures() {
		return numberNodeFeatures;
	}
	
	public void incNumberNodeFeatures(){
		numberNodeFeatures++;
	}
	
	/**
	 * 
	 * @return The ratio of the number of unique features involved in the feature model integrity constraint
	 * over all of the number of features in the feature model
	 */
	public double getCrossTreeConstraintsRatio(){
		return this.featuresOnConstraints.size()/(double)this.getNumberFeatures();
	}
	
	/**
	 * 
	 * @return the average number of children of the nodes in the feature model tree
	 */
	public double getRatioOfVariability(){
		return (double) numberChildrenFeatures/numberNodeFeatures;
	}
	
	/**
	 * The coefficient of connectivity represents how well the graph components are connected
	 * @return The ratio of the number of edges (number of features minus one)
	 * over the number of features in a feature model
	 */
	//TODO ratio of the number of edges is equals number of features minus one?? always??
	public double getCoeficientOfConnectivityDensity(){
		return (this.getNumberFeatures() - 1 + this.getNumberConstraints())
				/(double)this.getNumberFeatures();
	}
	
	/**
	 * 
	 * @return the ratio of the number of optional features over all of the available features
	 * in the feature model
	 */
	public double getFlexibilityOfConfigurationRatio(){
		return this.getNumberOptionalFeatures()/(double)this.getNumberFeatures();
	}

}
